// 
// Bachelor of Software Engineering
// Media Design School
// Auckland
// New Zealand
//
// (c) 2005 - 2014 Media Design School
//
// File Name	: SpaceInvadersLogic.cpp
// Desrciption	: CSpaceInvadersLogic implementation file.
// Author		: Hayden Asplet.
// Mail			: hayden.asplet@mediadesignschool.com
//

// PCH
#include "SpaceInvadersStd.h"

// Library Includes
#include <fstream>
#include <algorithm>

// This Include
#include "SpaceInvadersLogic.h"

// Local Includes
#include "Msvc\resource.h"
#include "SpaceInvadersHumanView.h"
#include "TitleScreenView.h"
#include "MenuScreenView.h"
#include "HighscoreScreenView.h"

CSpaceInvadersLogic::CSpaceInvadersLogic()
	:m_iWavesCompleted(0),
	m_cannonId(g_kINVALID_OBJECT_ID),
	m_fMysteryShipTime(0.0f),
	m_fMysteryShipTimeBuffer(0.0f),
	m_bIsGameOver(false)
{

}

CSpaceInvadersLogic::~CSpaceInvadersLogic()
{
	if(!m_highscores.empty()) {
		SaveHighScores("HighScores.txt");
	}
}

bool CSpaceInvadersLogic::VInit()
{
	if(!CGameLogic::VInit()) {
		return false;
	}

	LoadHighScores("HighScores.txt");

	// Sort the high scores.
	std::sort(m_highscores.begin(), m_highscores.end(), HighscoreCompare);

	return true;
}

void CSpaceInvadersLogic::VUpdate(float _fDeltaTime)
{
	CGameLogic::VUpdate(_fDeltaTime);	// Updates the elapsed time, game objects, views and fires queued events.

	switch(m_eState) {
		case GS_TitleScreen: {
			break;
		}
		case GS_MainMenu: {
			break;
		}
		case GS_HighScore: {
			break;
		}
		case GS_Options: {
			break;
		}
		case GS_Running: {
			if(m_bIsGameOver) {
				return;
			}

			// Increase the rate at which the aliens move slightly.
			m_alienWave.SetRate(m_alienWave.GetRate() - _fDeltaTime * g_kfALIEN_WAVE_RATE_INCREASE);

			// Update the alien wave.
			m_alienWave.Update(_fDeltaTime);

			if(m_alienWave.IsWaveCompleted()) {
			// Has the entire wave been defeated?
				// Increment amount of waves completed.
				++m_iWavesCompleted;

				// Create a new wave.
				m_alienWave.CreateWave(g_kiALIEN_WAVE_START_X, g_kiALIEN_WAVE_START_Y, 
									   g_kiALIEN_WAVE_COLUMNS, g_kiALIEN_WAVE_ROWS,
									   g_kiALIEN_WAVE_OFFSET, g_kiALIEN_WAVE_INCREMENT_Y * (m_iWavesCompleted + 1));

				TGameObjectMap::iterator iter;

				// Destroy all bullets and explosions.
				for(iter = m_gameObjects.begin(); iter != m_gameObjects.end();) {
					CGameObject* pTempObject = iter->second;

					// Increment before the iterator becomes unsuable.
					++iter;

					if(pTempObject->GetType() == "Bullet" || 
					   pTempObject->GetType() == "AlienBullet" || 
					   pTempObject->GetType() == "Explosion") {
						// Trigger an event to destroy the object.
						TEventDataPtr pEvent(new CEvtDataDestroyObject(pTempObject->GetId()));
						CEventManager::GetInstance()->TriggerEvent(pEvent);
					}
				}
			}

			// Check to see if the alien wave has reached the cannon.
			CGameObject* pCannon = GetGameObject(m_cannonId);

			if(pCannon) {
				shared_ptr<CPositionComponent> pCannonPosition = pCannon->GetComponent<CPositionComponent>();
				shared_ptr<CAnimationComponent> pCannonAnim = pCannon->GetComponent<CAnimationComponent>();

				if(m_alienWave.GetBottom() >= pCannonPosition->GetPosition().m_iY) {
					// The game has now ended.
					m_bIsGameOver = true;

					pCannonAnim->PlayAnimation("Death", g_kiSTANDARD_ANIM_SPEED, false);

					CreateGameObject("GameObjects\\GameOverText.xml");

					// Clear the alien wave.
					m_alienWave.ClearWave();

					// Stop all objects.
					TGameObjectMap::iterator iter;
					for(iter = m_gameObjects.begin(); iter != m_gameObjects.end(); ++iter) {
						shared_ptr<CPhysicsComponent> pPhysicsComponent = iter->second->GetComponent<CPhysicsComponent>();

						if(pPhysicsComponent) {
						// Does this object have a physics component.
							pPhysicsComponent->Stop();
						}
					}
				}
			}

			if(!m_alienWave.IsStopped()) {
				m_fMysteryShipTimeBuffer += _fDeltaTime;
			}

			if(m_fMysteryShipTime == 0.0f) {
				// Get a random mystery ship time.
				int iRandom = GetRandomNumber(g_kiMYSTERY_SHIP_MIN_TIME, g_kiMYSTERY_SHIP_MAX_TIME);

				m_fMysteryShipTime = static_cast<float>(iRandom);
			}

			if(m_fMysteryShipTimeBuffer > m_fMysteryShipTime) {
			// Time to spawn a mystery ship.
				// Set timers back.
				m_fMysteryShipTime = 0.0f;
				m_fMysteryShipTimeBuffer = 0.0f;

				CGameObject* pMysteryShip = CreateGameObject("GameObjects\\MysteryShip.xml");

				if(pMysteryShip) {
					// Queue an event to move the mysteryship.
					TEventDataPtr pEvent(new CEvtDataMoveObject(pMysteryShip->GetId(), true, 0, g_kfMYSTERY_SHIP_SPEED));
					CEventManager::GetInstance()->QueueEvent(pEvent);
				}
			}

			break;
		}
		default: {
			break;
		}
	}
}

void CSpaceInvadersLogic::VChangeState(EGameState _eState)
{
	switch(_eState) {
		case GS_TitleScreen: {
			// Create a title screen view and add it to the game.
			TStrongGameViewPtr titleView(new CTitleScreenView());
			AddView(titleView);
			break;
		}
		case GS_MainMenu: {
			// Remove current views.
			while(!m_gameViews.empty()) {
				m_gameViews.pop_back();
			}
			
			CGameObject* pMenuSelection = CreateGameObject("GameObjects\\MenuSelection.xml");

			// Create a menu screen view and add it to the game.
			if(pMenuSelection) {
				TStrongGameViewPtr menuView(new CMenuScreenView);
				AddView(menuView, pMenuSelection->GetId());
			}

			break;
		}
		case GS_HighScore: {
			// Remove current views.
			while(!m_gameViews.empty()) {
				m_gameViews.pop_back();
			}
			
			TStrongGameViewPtr highscoreView(new CHighscoreScreenView(&m_highscores));
			AddView(highscoreView);

			break;
		}
		case GS_Options: {
			break;
		}
		case GS_Running: {
			// Remove current views.
			while(!m_gameViews.empty()) {
				m_gameViews.pop_back();
			}

			// Create the human view for the player.
			TStrongGameViewPtr humanView(new CSpaceInvadersHumanView());

			// Create the laser cannon.
			CGameObject* laserCannon = CreateGameObject("GameObjects\\LaserCannon.xml");

			CreateGameObject("GameObjects\\BackgroundImage.xml");


			if(laserCannon) {
				// Add the view and attach the laser cannon to it.
				AddView(humanView, laserCannon->GetId());
				m_cannonId = laserCannon->GetId();
			}
			else {
			}

			CreateBunkers();

			m_iWavesCompleted = 0;

			// Create the alien wave.
			m_alienWave.CreateWave(g_kiALIEN_WAVE_START_X, g_kiALIEN_WAVE_START_Y, 
								   g_kiALIEN_WAVE_COLUMNS, g_kiALIEN_WAVE_ROWS,
								   g_kiALIEN_WAVE_OFFSET, g_kiALIEN_WAVE_INCREMENT_Y * (m_iWavesCompleted + 1));

			// Set the timers.
			m_fMysteryShipTime = 0.0f;
			m_fMysteryShipTimeBuffer = 0.0f;

			m_bIsGameOver = false;	// The game is not over, in fact it's just begun.

			break;
		}
		default: {
			break;
		}
	}

	CGameLogic::VChangeState(_eState);
}

void CSpaceInvadersLogic::VRegisterEventListeners()
{
	// Register Listeners
	CEventManager::GetInstance()->AddListener<CEvtDataCollision>(MakeDelegate(this, &CSpaceInvadersLogic::OnCollisionEvent));
	CEventManager::GetInstance()->AddListener<CEvtDataAnimFinish>(MakeDelegate(this, &CSpaceInvadersLogic::OnAnimationFinished));
	CEventManager::GetInstance()->AddListener<CEvtDataDestroyObject>(MakeDelegate(this, &CSpaceInvadersLogic::OnDestroyObject));

	// Let the base logic register it's listeners.
	CGameLogic::VRegisterEventListeners();
}

void CSpaceInvadersLogic::VRemoveEventListeners()
{
	// Remove Listeners
	CEventManager::GetInstance()->RemoveListener<CEvtDataCollision>(MakeDelegate(this, &CSpaceInvadersLogic::OnCollisionEvent));
	CEventManager::GetInstance()->RemoveListener<CEvtDataAnimFinish>(MakeDelegate(this, &CSpaceInvadersLogic::OnAnimationFinished));

	// Let the base logic remove it's listeners.
	CGameLogic::VRegisterEventListeners();
}

shared_ptr<CCannonComponent> CSpaceInvadersLogic::GetCannonComponent()
{
	CGameObject* pLaserCannon = GetGameObject(m_cannonId);

	if(pLaserCannon) {
		return pLaserCannon->GetComponent<CCannonComponent>();
	}
	else {
		return shared_ptr<CCannonComponent>();
	}
}

void CSpaceInvadersLogic::LoadHighScores(const std::string& _krstrFilePath)
{
	// Load highscores from document.
	std::ifstream ifs(_krstrFilePath.c_str());

	if(!ifs) {
		std::cerr << "ERROR: Failed to open file \"" << _krstrFilePath  << "\"" << std::endl;
		return;
	}

	std::string strLine;

	while(std::getline(ifs, strLine) && !ifs.eof()) {
		std::string strName = "";
		std::string strScore = "";
		int iScore = 0;
		bool bPastEquals = false;

		for(unsigned int i = 0; i < strLine.size(); ++i) {
			if(strLine[i] != ' ') {
			// Ignore white space.
				if(!bPastEquals) {
				// Are we passed the equal operator.
					if(strLine[i] == '=') { 
						bPastEquals = true;
					}
					else {
						// Add to the name string.
						strName += strLine[i];
					}
				}
				else {
					// Add to the score string.
					strScore += strLine[i];
				}
			}
			else {
			// Current character is white space.
				// Ignore it.
			}
		}

		// Convert score from string to integer.
		iScore = atoi(strScore.c_str());

		m_highscores.push_back(CHighScoreEntry(strName, iScore));
	}
}

void CSpaceInvadersLogic::SaveHighScores(const std::string& _krstrFilePath)
{
	// Load highscores from document.
	std::ofstream ofs(_krstrFilePath.c_str());

	if(!ofs) {
		std::cerr << "ERROR: Failed to open file \"" << _krstrFilePath  << "\"" << std::endl;
		return;
	}

	for(unsigned int i = 0; i < m_highscores.size(); ++i) {
		// Output current highscore to the file.
		if(m_highscores[i].GetName() != "") {
			ofs << m_highscores[i].GetName() << "=" << m_highscores[i].GetScore() << std::endl;
		}
	}
}

void CSpaceInvadersLogic::CreateBunkers()
{
	int iStartY = 500;
	int iStartX = 100;
	int iOffset = 200;
	int iBunkers = 4;
	int iWidth = 4;
	int iHeight = 3;

	for(int i = 0; i < iBunkers; ++i) {
		for(int j = 0; j < iWidth; ++j) {
			for(int k = 0; k < iHeight; ++k) {
				// Create the bunker piece.
				CGameObject* pBunkerPiece = CreateGameObject("GameObjects\\BunkerPiece.xml");

				// Get the animation component and the position component.
				shared_ptr<CAnimationComponent> pAnimComponent = pBunkerPiece->GetComponent<CAnimationComponent>();

				if(k == 0 && j == 0) {
					pAnimComponent->PlayAnimation("TopLeft", 0, false);
				}
				else if(k == 0 && j == iWidth - 1) {
					pAnimComponent->PlayAnimation("TopRight", 0, false);
				}
				else if(k == 1 && j == 1) {
					pAnimComponent->PlayAnimation("BottomLeft", 0, false);
				}
				else if(k == 1 && j == 2) {
					pAnimComponent->PlayAnimation("BottomRight", 0, false);
				}
				else if(k == iHeight - 1 && (j == 1 || j == 2)) {
					DestroyGameObject(pBunkerPiece->GetId());
					continue;
				}
				else {
					pAnimComponent->PlayAnimation("Middle", 0, false);
				}

				shared_ptr<CPhysicsComponent> pPhysicsComponent = pBunkerPiece->GetComponent<CPhysicsComponent>();
				shared_ptr<CPositionComponent> pPositionComponent = pBunkerPiece->GetComponent<CPositionComponent>();

				CPoint position(i * iOffset + iStartX, iStartY);
				CRect box = pPhysicsComponent->GetBoundingBox();

				position += CPoint(j * box.m_iWidth, k * box.m_iHeight);

				pPositionComponent->SetPosition(position);
			}
		}
	}
}

//=================================================================
// Event Listeners
//=================================================================

void CSpaceInvadersLogic::OnCollisionEvent(TEventDataPtr _pEventData)
{
	shared_ptr<CEvtDataCollision> pCollisionEventData = static_pointer_cast<CEvtDataCollision>(_pEventData);

	CGameObject* pFirst = GetGameObject(pCollisionEventData->GetObjectIdFirst());
	CGameObject* pSecond = GetGameObject(pCollisionEventData->GetObjectIdSecond());

	if(!pFirst || !pSecond) {
	// Objects with the id's of the collision event do not exist.
		return;
	}

	if((pFirst->GetType() == "Alien" && pSecond->GetType() == "Bullet") ||
		pFirst->GetType() == "Bullet" && pSecond->GetType() == "Alien") {
	// The player has hit an alien with a bullet.
		// Trigger events to destroy both game objects involved in the collision.
		TEventDataPtr pEventDestroyFirst(new CEvtDataDestroyObject(pFirst->GetId()));
		TEventDataPtr pEventDestroySecond(new CEvtDataDestroyObject(pSecond->GetId()));

		CEventManager::GetInstance()->TriggerEvent(pEventDestroyFirst);
		CEventManager::GetInstance()->TriggerEvent(pEventDestroySecond);
	}
	else if((pFirst->GetType() == "Bullet" || pFirst->GetType() == "AlienBullet") &&
			pSecond->GetType() == "BunkerPiece") {
	// A bullet or alien bullet has collided with a bunker piece.
		// Get the animation component of the bunker piece.
		shared_ptr<CAnimationComponent> pAnimComponent = pSecond->GetComponent<CAnimationComponent>();

		if(pAnimComponent) {
			// Move to the next frame on the bunker piece, 
			// showing a slightly more destroyed block.
			pAnimComponent->NextFrame();
		}

		// Destroy the bullet.
		TEventDataPtr pEvent(new CEvtDataDestroyObject(pFirst->GetId()));
		CEventManager::GetInstance()->TriggerEvent(pEvent);
	}
	else if(pFirst->GetType() == "MysterShip" && pSecond->GetType() == "Bullet") {
	// The player has hit an mystery ship with a bullet.
		shared_ptr<CCannonComponent> pCannonComponent = GetCannonComponent();
		shared_ptr<CAlienComponent> pAlienComponent = pFirst->GetComponent<CAlienComponent>();

		if(pAlienComponent && pCannonComponent) {
			// Get a random multiplier.
			int iRandom = GetRandomNumber(1, 4);

			// Increase the players score.
			pCannonComponent->AddToScore(pAlienComponent->GetWorth() * iRandom);
		}

		// Trigger events to destroy both game objects involved in the collision.
		TEventDataPtr pEventDestroyFirst(new CEvtDataDestroyObject(pFirst->GetId()));
		TEventDataPtr pEventDestroySecond(new CEvtDataDestroyObject(pSecond->GetId()));

		CEventManager::GetInstance()->TriggerEvent(pEventDestroyFirst);
		CEventManager::GetInstance()->TriggerEvent(pEventDestroySecond);
	}
	else if(pFirst->GetType() == "LaserCannon" && pSecond->GetType() == "AlienBullet")
	// The player has been hit by and alien bullet.
	{
		shared_ptr<CAnimationComponent> pAnimComponent = pFirst->GetComponent<CAnimationComponent>();

		if(pAnimComponent) {
			pAnimComponent->PlayAnimation("Death", g_kiSTANDARD_ANIM_SPEED, false);
		}

		// Stop the alien wave, whilst we display the death animation.
		m_alienWave.Stop();

		TGameObjectMap::iterator iter;

		// Destroy all bullets and explosions.
		for(iter = m_gameObjects.begin(); iter != m_gameObjects.end();) {
			CGameObject* pTempObject = iter->second;

			// Increment before the iterator becomes unsuable.
			++iter;

			if(pTempObject->GetType() == "Bullet" || 
			   pTempObject->GetType() == "AlienBullet" || 
			   pTempObject->GetType() == "Explosion") {
				// Trigger an event to destroy the object.
				TEventDataPtr pEvent(new CEvtDataDestroyObject(pTempObject->GetId()));
				CEventManager::GetInstance()->TriggerEvent(pEvent);
			}
		}

		shared_ptr<CCannonComponent> pCannonComponent = GetCannonComponent();

		if(pCannonComponent) {
			pCannonComponent->LoseLife();

			if(pCannonComponent->GetLives() <= 0) {
			// The player has run out of lives.
				// The game has now ended.
				m_bIsGameOver = true;

				CreateGameObject("GameObjects\\GameOverText.xml");

				// Clear the alien wave.
				m_alienWave.ClearWave();

				// Stop all objects.
				TGameObjectMap::iterator iter;
				for(iter = m_gameObjects.begin(); iter != m_gameObjects.end(); ++iter) {
					shared_ptr<CPhysicsComponent> pPhysicsComponent = iter->second->GetComponent<CPhysicsComponent>();

					if(pPhysicsComponent) {
					// Does this object have a physics component.
						pPhysicsComponent->Stop();
					}
				}
			}
		}
	}
	else if(pFirst->GetType() == "AlienBullet" && pSecond->GetType() == "LaserCannon")
	// The player has been hit by and alien bullet.
	{
		shared_ptr<CAnimationComponent> pAnimComponent = pSecond->GetComponent<CAnimationComponent>();

		if(pAnimComponent) {
			pAnimComponent->PlayAnimation("Death", g_kiSTANDARD_ANIM_SPEED, false);
		}

		// Stop the alien wave, whilst we display the death animation.
		m_alienWave.Stop();

		TGameObjectMap::iterator iter;

		// Destroy all bullets and explosions.
		for(iter = m_gameObjects.begin(); iter != m_gameObjects.end();) {
			CGameObject* pTempObject = iter->second;

			// Increment before the iterator becomes unsuable.
			++iter;

			if(pTempObject->GetType() == "Bullet" || 
			   pTempObject->GetType() == "AlienBullet" || 
			   pTempObject->GetType() == "Explosion") {
				// Trigger an event to destroy the object.
				TEventDataPtr pEvent(new CEvtDataDestroyObject(pTempObject->GetId()));
				CEventManager::GetInstance()->TriggerEvent(pEvent);
			}
		}

		shared_ptr<CCannonComponent> pCannonComponent = GetCannonComponent();

		if(pCannonComponent) {
			pCannonComponent->LoseLife();

			if(pCannonComponent->GetLives() <= 0) {
			// The player has run out of lives.
				// The game has now ended.
				m_bIsGameOver = true;

				CreateGameObject("GameObjects\\GameOverText.xml");

				// Clear the alien wave.
				m_alienWave.ClearWave();

				// Stop all objects.
				TGameObjectMap::iterator iter;
				for(iter = m_gameObjects.begin(); iter != m_gameObjects.end(); ++iter) {
					shared_ptr<CPhysicsComponent> pPhysicsComponent = iter->second->GetComponent<CPhysicsComponent>();

					if(pPhysicsComponent) {
					// Does this object have a physics component.
						pPhysicsComponent->Stop();
					}
				}
			}
		}
	}
	else if(pFirst->GetType() == "Bullet" && pSecond->GetType() == "LaserCannon") {
		shared_ptr<CCannonComponent> pCannonComponent = GetCannonComponent();

		// Destroy the bullet.
		DestroyGameObject(pFirst->GetId());
	}
}

void CSpaceInvadersLogic::OnAnimationFinished(TEventDataPtr _pEventData)
{
	shared_ptr<CEvtDataAnimFinish> pAnimFinishEventData = static_pointer_cast<CEvtDataAnimFinish>(_pEventData);

	CGameObject* pObject = GetGameObject(pAnimFinishEventData->GetObjectId());

	if(!pObject) {
	// Objects with the id's of the collision event do not exist.
		return;
	}

	if(pAnimFinishEventData->GetAnimationName() == "Death") {
		shared_ptr<CAnimationComponent> pAnimComponent = pObject->GetComponent<CAnimationComponent>();
		shared_ptr<CPhysicsComponent> pPhysicsComponent = pObject->GetComponent<CPhysicsComponent>();
		shared_ptr<CPositionComponent> pPositionComponent = pObject->GetComponent<CPositionComponent>();
		shared_ptr<CCannonComponent> pCannonComponent = GetCannonComponent();

		if(m_bIsGameOver) {
			return;
		}

		if(pAnimComponent) {
			pAnimComponent->PlayAnimation("Default", 0, true);
		}

		if(pPhysicsComponent && pPositionComponent) {
			// Move the laser cannon back to the centre.
			CPoint position = pPositionComponent->GetPosition();
			position.m_iX = g_pApp->GetScreenSize().m_iX / 2 - pPhysicsComponent->GetWorldBoundingBox().m_iWidth;

			pPositionComponent->SetPosition(position);
		}

		m_alienWave.Continue();
	}
	else if(pObject->GetType() == "BunkerPiece") {
		// The bunker piece has been shot so much it's now destroyed entirely.

		// Destroy it.
		DestroyGameObject(pObject->GetId());
	}
}

void CSpaceInvadersLogic::OnDestroyObject(TEventDataPtr _pEventData)
{
	shared_ptr<CEvtDataDestroyObject> pEvent = static_pointer_cast<CEvtDataDestroyObject>(_pEventData);

	// Get the object that's about to be destroyed.
	CGameObject* pObject = GetGameObject(pEvent->GetObjectId());

	if(pObject) {
	// Object retrieved fine.
		if(pObject->GetType() == "Alien") {
			CGameObject* pExplosion = CreateGameObject("GameObjects\\Explosion.xml");

			if(pExplosion) {
				// Get the position components so that we can set the explosion position to that of the alien
				shared_ptr<CPositionComponent> pAlienPosition = pObject->GetComponent<CPositionComponent>();
				shared_ptr<CPositionComponent> pExplosionPosition = pExplosion->GetComponent<CPositionComponent>();

				if(pExplosionPosition && pAlienPosition) {
					pExplosionPosition->SetPosition(pAlienPosition->GetPosition());
				}
			}

			if(pObject->GetType() == "Alien") {
				shared_ptr<CCannonComponent> pCannonComponent = GetCannonComponent();
				shared_ptr<CAlienComponent> pAlienComponent = pObject->GetComponent<CAlienComponent>();

				if(pAlienComponent && pCannonComponent) {
					// Increase the players score.
					pCannonComponent->AddToScore(pAlienComponent->GetWorth());
				}
		
				// Remove the alien id from the wave of aliens.
				m_alienWave.DestroyAlien(pObject->GetId());
			}
		}
		else if(pObject->GetType() == "Bullet") {
			// Get the cannon component of the laser cannon.
			shared_ptr<CCannonComponent> pCannonComponent = GetCannonComponent();

			if(pCannonComponent) {
				// Add back the ammo.
				pCannonComponent->AddToAmmo();
			}
		}
		else if(pObject->GetType() == "GameOverText") {
			// The game has now ended.
			// Remove the current views from the game.
			while(!m_gameViews.empty()) {
				RemoveView(m_gameViews.front());
			}

			shared_ptr<CCannonComponent> pCannonComponent = GetCannonComponent();

			if(pCannonComponent) {
				// Add back the ammo.
				m_highscores.push_back(CHighScoreEntry("", pCannonComponent->GetScore()));
				std::sort(m_highscores.begin(), m_highscores.end(), HighscoreCompare);
			}

			while(!m_gameObjects.empty()) {
				DestroyGameObject(m_gameObjects.begin()->first);
			}

			// Goto the highscore state.
			VChangeState(GS_HighScore);
		}
	}
	else {
	// We couldn't retrieve the object
	}
}

CObjectFactory* CSpaceInvadersLogic::VCreateObjectFactory()
{
	return new CSpaceInvadersObjectFactory();
}